package nivalsoul.kettle.plugins.util;

import java.io.File;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import cn.hutool.core.util.CharsetUtil;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class HttpTool {
	
	public static String get(String url, Map<String, Object> headers){
		String result = null;
		try {
			CloseableHttpClient httpclient = getClient(headers);
			HttpGet httpGet = new HttpGet(url);
			for(String key : headers.keySet()){
				httpGet.setHeader(key, headers.get(key).toString());
			}
		    CloseableHttpResponse response = httpclient.execute(httpGet);
		    try{
				HttpEntity entity = response.getEntity();
				if (entity != null){
					result = EntityUtils.toString(entity);
				}
			}finally {
				response.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	    return result;
	}


	/**
	 * Post请求
	 * @param url 请求地址
	 * @param params 参数列表
	 * @return 请求结果正文
	 */
	public static String post(String url, Map<String, Object> headers, Map<String, String>params) {
		String result = null;
		try{
			CloseableHttpClient httpclient = getClient(headers);
			HttpPost httpPost = new HttpPost(url);
			for(String key : headers.keySet()){
				httpPost.setHeader(key, headers.get(key).toString());
			}
	        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
	        Iterator<Entry<String, String>> iter = params.entrySet().iterator();
	        while (iter.hasNext()) {
	        	Entry<String, String> entry = iter.next();
	        	String key = entry.getKey();
	        	String val = entry.getValue();
	        	nvps.add(new BasicNameValuePair(key, val));
	        }
	        httpPost.setEntity(new UrlEncodedFormEntity(nvps,"UTF-8"));
	        CloseableHttpResponse response = httpclient.execute(httpPost);
			try{
				HttpEntity entity = response.getEntity();
				if (entity != null){
					result = EntityUtils.toString(entity);
				}
			}finally {
				response.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return result;
	}
	
	/**
	 * Post请求
	 * @param url
	 * @param bodyJson json字符串
	 * @return
	 */
	public static String post(String url, Map<String, Object> headers, String bodyJson) {
		String result = null;
		try{
			CloseableHttpClient httpclient = getClient(headers);
			HttpPost httpPost = new HttpPost(url);
			for(String key : headers.keySet()){
				httpPost.setHeader(key, headers.get(key).toString());
			}
			StringEntity jsonEntity = new StringEntity(bodyJson, "UTF-8");
			jsonEntity.setContentType("application/json");
	        httpPost.setEntity(jsonEntity);
	        CloseableHttpResponse response = httpclient.execute(httpPost);
			try{
				HttpEntity entity = response.getEntity();
				if (entity != null){
					result = EntityUtils.toString(entity);
				}
			}finally {
				response.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return result;
	}
	
	public static String upload(String url, Map<String, Object> headers, File[] files) {
		String result = null;
		if (files == null || files.length==0) {
			return result;
		}
		try{
			CloseableHttpClient httpclient = getClient(headers);
			HttpPost httpPost = new HttpPost(url);
			for(String key : headers.keySet()){
				httpPost.setHeader(key, headers.get(key).toString());
			}
	        MultipartEntityBuilder meb = MultipartEntityBuilder.create();
	        for(int i=0;i<files.length;i++){
	        	FileBody fb = new FileBody(files[i]);
	 			meb.addPart("file", fb);
	        }
	        HttpEntity me = meb
					.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
					.setCharset(CharsetUtil.charset("UTF-8")).build();
			httpPost.setEntity(me);
	        CloseableHttpResponse response = httpclient.execute(httpPost);
			try{
				HttpEntity entity = response.getEntity();
				if (entity != null){
					result = EntityUtils.toString(entity);
				}
			}finally {
				response.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return result;
	}

	private static CloseableHttpClient getClient(Map<String, Object> headers) {
		HttpClientBuilder custom = HttpClients.custom();
		if(headers.containsKey("loginUser") && headers.containsKey("loginPass")) {
			CredentialsProvider provider = new BasicCredentialsProvider();
			String loginUser = (String) headers.get("loginUser");
			String loginPass = (String) headers.get("loginPass");
			if(loginUser!=null && !loginUser.equals("") && loginPass!=null && !loginPass.equals("")) {
				provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(loginUser, loginPass));
			}
		}
		//请求https绕过认证的方法
		if((boolean)headers.getOrDefault("useSSL", false)) {
			try {
				//SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 在JSSE中，证书信任管理器类就是实现了接口X509TrustManager的类。我们可以自己实现该接口，让它信任我们指定的证书。
				// 创建SSLContext对象，并使用我们指定的信任管理器初始化
				//信任所有
				X509TrustManager x509mgr = new X509TrustManager() {
					//　　该方法检查客户端的证书，若不信任该证书则抛出异常
					public void checkClientTrusted(X509Certificate[] xcs, String string) {
					}

					// 　　该方法检查服务端的证书，若不信任该证书则抛出异常
					public void checkServerTrusted(X509Certificate[] xcs, String string) {
					}

					// 　返回受信任的X509证书数组。
					public X509Certificate[] getAcceptedIssuers() {
						return null;
					}
				};
				SSLContext sslContext = SSLContext.getInstance("TLS");
				sslContext.init(null, new TrustManager[]{x509mgr}, null);
				////创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
				SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

				//  HttpsURLConnection对象就可以正常连接HTTPS了，无论其证书是否经权威机构的验证，只要实现了接口X509TrustManager的类MyX509TrustManager信任该证书。
				custom.setSSLSocketFactory(sslsf);

			} catch (KeyManagementException e) {
				e.printStackTrace();
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return custom.build();
	}

}
